#ifndef __EB_VFS_H__
#define __EB_VFS_H__


#include <types.h>
#include <list.h>
#include <kernel/kobject.h>
#include <kernel/syslog.h>
#include <stdio.h>


#define  VFS_SYSLOG_INFO(...)            SYSLOG_INFO("VFS: "__VA_ARGS__)
#define  VFS_SYSLOG_ERROR(...)           SYSLOG_ERROR("VFS: "__VA_ARGS__)
#define  VFS_SYSLOG_WARN(...)            SYSLOG_WARN("VFS: "__VA_ARGS__)
#define  VFS_DEBUG_TRACE(...)            DEBUG_TRACE("VFS: "__VA_ARGS__)


#define  VFS_MAX_PATH                    (128)
#define  VFS_MAX_NAME                    (64)
#define  VFS_MAX_FD                      (128)


#define	 R_OK				             (1 << 2)
#define	 W_OK				             (1 << 1)
#define	 X_OK				             (1 << 0)


#define  VFS_SEEK_SET		             (0)
#define  VFS_SEEK_CUR		             (1)
#define  VFS_SEEK_END		             (2)


/* 在文件打开过程中创建新文件 */
#define O_CREAT                          (1 << 0)
/* 以只读方式打开文件 */
#define O_RDONLY			             (1 << 1)
/* 以只写方式打开文件 */
#define O_WRONLY			             (1 << 2)
/* 以读写方式打开文件 */
#define O_RDWR				             (O_RDONLY | O_WRONLY)
/* 在文件末尾追加数据，而不是覆盖现有内容 */
#define O_APPEND                         (1 << 3)
/* 如果文件已经存在，将其截断为空文件 */
#define O_TRUNC                          (1 << 4)
/* 与 O_CREAT 一起使用时，如果文件已经存在，则 open() 调用将失败 */
#define O_EXCL                           (1 << 5)
/* 使文件写操作变为同步写入，即将数据立即写入磁盘 */
#define O_SYNC                           (1 << 6)
/* 以非阻塞方式打开文件，即使无法立即进行读写操作也不会被阻塞 */
#define O_NONBLOCK                       (1 << 7)


/* 普通文件 */
#define	S_IFREG				             (1 << 12)
/* 目录文件 */
#define	S_IFDIR				             (1 << 13)
/* 字符设备文件 */
#define	S_IFCHR				             (1 << 14)
/* 块设备文件 */
#define	S_IFBLK				             (1 << 15)
/* 链接文件 */
#define	S_IFLNK				             (1 << 16)
/* 管道文件 */
#define	S_IFIFO				             (1 << 17)
/* Socket文件 */
#define	S_IFSOCK			             (1 << 18)
/* 文件类型掩码 */
#define S_IFMT                           (S_IFREG | S_IFDIR | S_IFCHR | S_IFBLK | S_IFLNK | S_IFIFO | S_IFSOCK)


/* 判断文件是否是普通文件 */
#define S_ISREG(m)                       (((m) & S_IFMT) == S_IFREG)
/* 判断文件是否是目录文件 */
#define S_ISDIR(m)                       (((m) & S_IFMT) == S_IFDIR)
/* 判断文件是否是字符设备文件 */
#define S_ISCHR(m)                       (((m) & S_IFMT) == S_IFCHR)
/* 判断文件是否是块设备文件 */
#define S_ISBLK(m)                       (((m) & S_IFMT) == S_IFBLK)
/* 判断文件是否是链接文件 */
#define S_ISLNK(m)                       (((m) & S_IFMT) == S_IFLNK)
/* 判断文件是否是管道文件 */
#define S_ISFIFO(m)                      (((m) & S_IFMT) == S_IFIFO)
/* 判断文件是否是Socket文件 */
#define S_ISSOCK(m)                      (((m) & S_IFMT) == S_IFSOCK)


struct file_system_type;

//st_mode: {f,d,l,b,c,s} {r,w,x}


struct vfs_stat {
    /* ID of device containing file */
    uint64_t st_dev;
    /* inode number */
	uint64_t st_ino;
    /* file permission and file type*/
    uint32_t st_mode;
    /* block size, in sector(512Byte) */
    // uint16_t st_blksize;
    // /* block count  */
    // uint16_t st_blocks;
    // /* total file size, in bytes*/
	int64_t  st_size;
	/* time of last access */
	uint64_t st_atime;
    /* time of last modification */
	uint64_t st_mtime;
    /* time of last status change */
    uint64_t st_ctime;
};


struct vfs_inode {
    /* file permission and file type*/
    uint32_t i_mode;
    /* 文件的块数 */
    uint32_t i_blocks;
    /* inode number */
    uint64_t i_ino;
    /* 原子操作，引用计数 */
    uint64_t i_count;
    /* 文件大小，单位字节 */
    int64_t i_size;
    /* time of last access */
	uint64_t st_atime;
    /* time of last modification */
	uint64_t st_mtime;
    /* time of last status change */
    uint64_t st_ctime;
};


struct vfs_mount;


struct vfs_file {
    /* 指向inode指针 */
    struct vfs_inode *f_node;
	off_t    f_offset;
	uint32_t f_flags;
    struct vfs_mount *f_mnt;
};


struct vfs_dentry {
    struct vfs_inode *d_inode;
    char d_name[VFS_MAX_NAME];
    struct vfs_dentry *d_parent;
    list_node_t d_sub;
    list_node_t link;
};


struct file_operations {
    int (*open)(struct vfs_file *file, int flags);
    int (*close)(struct vfs_file *file);
    int (*read)(struct vfs_file *file, void *buf, int len);
    int (*write)(struct vfs_file *file, const void *buf, int len);
    int (*lseek)(struct vfs_file *file, off_t offset);
    int (*stat)(struct vfs_file *file, struct vfs_stat *st);
    int (*ioctl)(struct vfs_file *file, int cmd, void *arg);
    int (*poll)(struct vfs_file *file, int events);
    int (*mkdir)(struct vfs_file *file, const char *path, uint32_t mode);
    int (*rmdir)(struct vfs_file *file, const char *path);
};


struct vfs_mount {
    /* 挂在的位置 */
    char m_path[VFS_MAX_PATH];
    /* 挂载的根目录 */
    struct vfs_dentry *m_root;
    /* 文件系统类型 */
    struct file_system_type *m_type;
    /* 挂载的设备名称 */
    const char *m_dev;
    list_node_t link;
};


struct file_system_type {
    const char  *name;
    uint32_t    s_magic;
    list_node_t link;
    int (*mount)(struct file_system_type *fs_type, const char *m_dev);
    int (*unmount)(struct vfs_mount* mnt);
    struct file_operations *f_ops;
};


int vfs_mount(const char *fs_name, const char *dev, const char *mnt_point);
int vfs_umount(const char *mnt_point);


int vfs_open(const char *path, int flags);
int vfs_close(int fd);
int vfs_read(int fd, void *buf, int len);
int vfs_write(int fd, const void *buf, int len);
int vfs_lseek(int fd, off_t offset);
int vfs_ioctl(int fd, int cmd, void *arg);
int vfs_mkdir(const char *path);


// int vfs_open(const char *path, int flags)
// {

// }

// int vfs_close(int fd)
// {

// }

// int vfs_read(int32_t fd, void *buf, uint32_t nbytes)
// {

// }

// int vfs_write(int32_t fd, void *buf, uint32_t nbytes)
// {

// }


// int vfs_ioctl(int32_t fd, int32_t cmd, uint32_t arg)
// {

// }

// int vfs_lseek(int32_t fd, int32_t offset, int32_t whence)
// {

// }


// int vfs_mkdir(const char *path)
// {

// }


// int vfs_rmdir(const char *path)
// {

// }


// int vfs_chdir(const char *path)
// {

// }

// int vfs_stat(const char *path, struct vfs_stat *buf)
// {

// }


// int vfs_access(const char *path, int32_t amode)
// {

// }


#endif //!__EB_VFS_H__
